using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Globalization;
using System.Xml.Serialization;
using CommonUtils;

namespace ShellAnywhere.Model
{
	using ParamToken = Token<IParam>;
	using ActionToken = Token<IAction>;

	using CharStream = Stream<char>;
	using ParamTokenStream = Stream<Token<IParam>>;
	using ActionTokenStream = Stream<Token<IAction>>;

	public class LaunchMgr : ActionMgr
	{
		#region verbs
		public static IVerb NEW = new New();
		public static IVerb OPEN = new Open();
		public static IVerb EMPTY = new Alias(string.Empty, OPEN);
		#endregion verbs

		#region ctors
		public LaunchMgr(Action<string> stdOut, Action<string> stdErr, Shell[] shells, params string[] targets)
		{
			_StdOut = stdOut;
			_StdErr = stdErr;
			_PrimaryShell = null;
			_Shells = new Dictionary<string, Shell>();
			if (shells != null && shells.Length > 0)
			{
				foreach (Shell shell in shells)
					AddShell(shell);
				PrimaryShell = shells[0];
			}

			_Targets = targets;

			_Lexer = new Lexer(_CharStream, _ParamTokenStream);
			_Parser = new Parser(this, _ParamTokenStream, _ActionTokenStream, EMPTY);
		}
		#endregion ctors

		#region props
		public Shell PrimaryShell
		{
			get { return _PrimaryShell; }
			set
			{
				if (_PrimaryShell != null && _PrimaryShell != value)
					_PrimaryShell.Stop();
				_PrimaryShell = value;
				_PrimaryShell.Start(_StdOut, _StdErr);
			}
		}
		public override string[] Targets
		{
			get
			{
				List<string> targets = new List<string>();
				targets.Add(CurrentDirectory);
				targets.AddRange(_Targets);
				return targets.ToArray();
			}
		}
		#endregion props

		#region methods
		public override void Init() { Load(Targets); }
		public override void End() { }

		public override bool Advance()
		{
			return Current.Execute();
		}
		public override bool Withdraw()
		{
			return UserInputBackspace();
		}
		public void AddShell(Shell shell)
		{
			try
			{
				_Shells[shell.Name] = shell;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}
		public void DelShell(Shell shell)
		{
			_Shells.Remove(shell.Name);
		}
		public IActionMgr SetPosture(Posture posture)
		{
			_Posture = posture;
			return this;
		}
		public override void Load(params string[] targetsAndDirectories)
		{
			//TargetList list = new TargetList();
			//list.Add(NEW);
			//list.Add(OPEN);
			//list.Add(EMPTY);
			//list.AddRange(LoadTargets(targets));
			List<ITarget> list = new List<ITarget>();
			list.Add(NEW);
			list.Add(OPEN);
			list.Add(EMPTY);
			list.AddRange(LoadTargets(targetsAndDirectories));

			_Lexer.InitStateTree(list);
		}
		#endregion methods

		#region events
		#endregion events

		#region fields
		private Action<string> _StdOut;
		private Action<string> _StdErr;
		private Shell _PrimaryShell;
		private Dictionary<string, Shell> _Shells;
		private string[] _Targets;
		private Posture _Posture;
		#endregion fields
	}
}
